package reduce.fz.com.reduce.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.util.LruCache;
import android.widget.ImageView;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import jp.co.cyberagent.android.gpuimage.GPUImageView;
import reduce.fz.com.reduce.R;

/**
 * 从SDCard异步加载图片
 *
 */
public class SDCardImageLoader {
    //缓存
    private LruCache<String, Bitmap> imageCache;
    // 固定3个线程来执行任务
    private ExecutorService executorService = Executors.newFixedThreadPool(3);
    private Handler handler = new Handler();

    private int screenW, screenH;

    public SDCardImageLoader(int screenW, int screenH, LruCache lruCache) {
        imageCache = lruCache;
        this.screenW = screenW;
        this.screenH = screenH;

//        // 获取应用程序最大可用内存
//        int maxMemory = (int) Runtime.getRuntime().maxMemory();
//        int cacheSize = maxMemory / 8;
//
//        // 设置图片缓存大小为程序最大可用内存的1/8
//        imageCache = new LruCache<String, Bitmap>(cacheSize) {
//            @Override
//            protected int sizeOf(String key, Bitmap value) {
//                return value.getRowBytes() * value.getHeight();
//            }
//        };
    }

    private String getCacheKey(String filePath , int smallRate){
        return filePath + "_" +smallRate;
    }

    /**
     * 清理cache里面的缓存
     * @param filePath
     */
    public void clearFileCache(String filePath , int smallRate){
        String cacheKey = getCacheKey(filePath , smallRate);
        imageCache.remove(cacheKey);
        String cacheKey2 = filePath + "_compress";
        imageCache.remove(cacheKey2);
    }

    public Bitmap loadDrawable(final int smallRate, final String filePath,
                                final ImageCallback callback) {
        if(filePath == null){
            return null;
        }

        final String cacheKey = getCacheKey(filePath , smallRate);
        // 如果缓存过就从缓存中取出数据
        if (imageCache.get(cacheKey) != null) {
            return imageCache.get(cacheKey);
        }

        // 如果缓存没有则读取SD卡
        executorService.submit(new Runnable() {
            public void run() {
                try {
                    BitmapFactory.Options opt = new BitmapFactory.Options();
                    opt.inJustDecodeBounds = true;
                    BitmapFactory.decodeFile(filePath, opt);

                    // 获取到这个图片的原始宽度和高度
                    int picWidth = opt.outWidth;
                    int picHeight = opt.outHeight;

                    //读取图片失败时直接返回
                    if (picWidth == 0 || picHeight == 0) {
                        return;
                    }

                    //初始压缩比例
                    opt.inSampleSize = smallRate;
                    // 根据屏的大小和图片大小计算出缩放比例
                    if (picWidth > picHeight) {
                        if (picWidth > screenW)
                            opt.inSampleSize *= picWidth / screenW;
                    } else {
                        if (picHeight > screenH)
                            opt.inSampleSize *= picHeight / screenH;
                    }

                    //这次再真正地生成一个有像素的，经过缩放了的bitmap
                    opt.inJustDecodeBounds = false;

                    final Bitmap bmp = BitmapFactory.decodeFile(filePath, opt);
                    //存入map
                    if( cacheKey != null && bmp != null ){
                        imageCache.put(cacheKey, bmp);
                    }
                    handler.post(new Runnable() {
                        public void run() {
                            try{
                                callback.imageLoaded(bmp);
                            } catch (Throwable e){
                                ReduceLog.e(e);
                            }
                        }
                    });
                } catch (OutOfMemoryError e){
                }catch (Throwable e) {
                    ReduceLog.e(e);
                }
            }
        });

        return null;
    }

    /**
     * 异步读取SD卡图片，并按指定的比例进行压缩（最大不超过屏幕像素数）
     *
     * @param smallRate 压缩比例，不压缩时输入1，此时将按屏幕像素数进行输出
     * @param filePath  图片在SD卡的全路径
     * @param imageView 组件
     */
    public void loadImage( int smallRate , final String filePath, final ImageView imageView ) {
        if(imageView == null || filePath == null){
            return;
        }
        imageView.setTag(filePath);

        Bitmap bmp = loadDrawable(smallRate, filePath, new ImageCallback() {

            @Override
            public void imageLoaded(Bitmap bmp) {
                try{
                    if (imageView != null && filePath != null && imageView.getTag() != null && imageView.getTag().equals(filePath)) {
                        if (bmp != null) {
                            imageView.setImageBitmap(bmp);
                        } else {
                            imageView.setImageResource(R.drawable.empty_photo);
                        }
                    }
                } catch (Throwable e){
                    ReduceLog.e(e);
                }
            }
        });

        if (bmp != null) {
            if (imageView.getTag().equals(filePath)) {
                imageView.setImageBitmap(bmp);
            }
        } else {
            imageView.setImageResource(R.drawable.empty_photo);
        }

    }

    /**
     * 从file加载压缩以后的图片，该图片符合上传到Feel的图片质量
     * @param filePath
     * @param callback
     * @return
     */
    public Bitmap loadCompressBitmap( final String filePath , final ImageCallback callback ) {
        if(filePath == null){
            return null;
        }

        final String cacheKey = filePath + "_compress";
        // 如果缓存过就从缓存中取出数据
        if (imageCache.get(cacheKey) != null) {
            return imageCache.get(cacheKey);
        }

        // 如果缓存没有则读取SD卡
        executorService.submit(new Runnable() {
            public void run() {
                try {
                    final Bitmap bmp =  ImageCompressUtil.compressByQuality(filePath);
                    //存入map
                    imageCache.put(cacheKey, bmp);

                    handler.post(new Runnable() {
                        public void run() {
                            callback.imageLoaded(bmp);
                        }
                    });
                } catch (Throwable e) {
                    ReduceLog.e(e);
                }
            }
        });

        return null;
    }

    /**
     * 异步读取SD卡图片，并按指定的比例进行压缩（最大不超过屏幕像素数）
     *
     * @param filePath  图片在SD卡的全路径
     * @param imageView 组件
     */
    public void loadCompressImage(final String filePath, final ImageView imageView, final OnLoadCompleteListener onLoadCompleteListener) {
        imageView.setTag(filePath);

        Bitmap bmp = loadCompressBitmap(filePath, new ImageCallback() {

            @Override
            public void imageLoaded(Bitmap bmp) {
                try{
                    if( imageView != null && imageView.getTag() != null && filePath != null ){
                        if (imageView.getTag().equals(filePath)) {
                            if (bmp != null) {
                                imageView.setImageBitmap(bmp);
                                if(onLoadCompleteListener != null){
                                    onLoadCompleteListener.onLoadComplete(bmp);
                                }
                            } else {
                                imageView.setImageResource(R.drawable.empty_photo);
                                if(onLoadCompleteListener != null){
                                    onLoadCompleteListener.onLoadComplete(null);
                                }
                            }
                        }
                    }
                } catch ( Throwable e ){
                    ReduceLog.e(e);
                }
            }
        });

        if (bmp != null) {
            if (imageView.getTag().equals(filePath)) {
                imageView.setImageBitmap(bmp);
                if(onLoadCompleteListener != null){
                    onLoadCompleteListener.onLoadComplete(bmp);
                }
            }
        } else {
            imageView.setImageResource(R.drawable.image_error_background_gray);
        }

    }
    /**
     * 异步读取SD卡图片，并按指定的比例进行压缩（最大不超过屏幕像素数）
     *
     * @param filePath  图片在SD卡的全路径
     * @param gpuImageView 组件
     */
    public void loadCompressImage(final String filePath, final GPUImageView gpuImageView, final OnLoadCompleteListener onLoadCompleteListener) {
        gpuImageView.setTag(filePath);

        Bitmap bmp = loadCompressBitmap(filePath, new ImageCallback() {
            @Override
            public void imageLoaded(Bitmap bmp) {
                try{
                    if( gpuImageView != null && gpuImageView.getTag() != null && filePath != null ){
                        if (gpuImageView.getTag().equals(filePath)) {
                            gpuImageView.deleteImage();
                            if (bmp != null) {
                                gpuImageView.setImage(bmp);
                                if(onLoadCompleteListener != null){
                                    onLoadCompleteListener.onLoadComplete(bmp);
                                }
                            } else {
                                gpuImageView.setImageResource(R.drawable.empty_photo);
                                if(onLoadCompleteListener != null){
                                    onLoadCompleteListener.onLoadComplete(null);
                                }
                            }
                        }
                    }
                } catch ( Throwable e ){
                    ReduceLog.e(e);
                }
            }
        });

        if (bmp != null) {
            if (gpuImageView.getTag().equals(filePath)) {
                gpuImageView.deleteImage();
                gpuImageView.setImage(bmp);
                if(onLoadCompleteListener != null){
                    onLoadCompleteListener.onLoadComplete(bmp);
                }
            }
        } else {
            gpuImageView.deleteImage();
            gpuImageView.setImageResource(R.drawable.image_error_background_gray);
        }

    }


    // 对外界开放的回调接口
    public interface ImageCallback {
        // 注意 此方法是用来设置目标对象的图像资源
        public void imageLoaded(Bitmap imageDrawable);
    }

    public interface OnLoadCompleteListener{
        public void onLoadComplete(Bitmap bitmap);
    }
}
